#include "stdafx.h"
#include "Box3d.h"
#include "Vector3d.h"
#include "Matrix3d.h"
#include "Point3D.h"
#include "GeomUtils.h"

using namespace stl;

/////////////////////////////////////////////////////////////////////////////////////
//constructor && destructor
CBox3D::CBox3D()
{
	x0 = y0 = z0 = x1 = y1 = z1 = 0;
}

CBox3D::CBox3D(double ix0, double iy0, double iz0, double ix1, double iy1, double iz1)
{
	x0 = ix0; y0 = iy0; z0 = iz0; x1 = ix1; y1 = iy1; z1 = iz1;
	normalize();
}

CBox3D::CBox3D(POINT3D pt0, POINT3D pt1)
{
	x0 = pt0.x; y0 = pt0.y; z0 = pt0.z; x1 = pt1.x; y1 = pt1.y; z1 = pt1.z;
	normalize();
}

CBox3D::CBox3D(BOX3D b)
{
	x0 = b.x0; y0 = b.y0; z0 = b.z0;
	x1 = b.x1; y1 = b.y1; z1 = b.z1;
	normalize();
}

CBox3D::CBox3D(POINT3D p, VECTOR3D v)
{
	x0 = p.x; y0 = p.y; z0 = p.z;
	x1 = p.x + v.x;
	y1 = p.x + v.y;
	z1 = p.x + v.z;
	normalize();
}

CBox3D::~CBox3D()
{
}

// operator
//// get the union box of this and box b.
CBox3D CBox3D::operator+(BOX3D b) const
{
	CBox3D box = *this;

	if (((CBox3D)b).IsEmpty()) return  box;
	if (IsEmpty()) return b;

	box.x0 = (x0 < b.x0) ? x0 : b.x0;
	box.y0 = (y0 < b.y0) ? y0 : b.y0;
	box.z0 = (z0 < b.z0) ? z0 : b.z0;
	box.x1 = (x1 > b.x1) ? x1 : b.x1;
	box.y1 = (y1 > b.y1) ? y1 : b.y1;
	box.z1 = (z1 > b.z1) ? z1 : b.z1;

	return box;
}

void CBox3D::operator*= (double sc)
{
	x0 = x0 * sc;
	y0 = y0 * sc;
	z0 = z0 * sc;
	x1 = x1 * sc;
	y1 = y1 * sc;
	z1 = z1 * sc;
}

CBox3D CBox3D::operator*(const MATRIX3D& matrix) const
{
	CPoint3D p0(x0, y0, z0);
	CPoint3D p1(x1, y1, z1);

	p0 *= matrix;
	p1 *= matrix;

	return 	CBox3D(p0, p1);
}

void CBox3D::operator*=(const MATRIX3D& matrix)
{
	(*this) = (*this)*matrix;
}

CBox3D CBox3D::operator*(double sc) const
{
	CBox3D box;
	box.x0 = x0 * sc;
	box.y0 = y0 * sc;
	box.z0 = z0 * sc;
	box.x1 = x1 * sc;
	box.y1 = y1 * sc;
	box.z1 = z1 * sc;
	return box;
}

void CBox3D::operator+=(BOX3D b)
{
	CBox3D box = (*this) + b;
	(*this) = box;
}

//// get the intersect box of this and box b.
CBox3D CBox3D::operator&(BOX3D b) const
{
	CBox3D box;

	if (((CBox3D)b).IsEmpty() || ((CBox3D *)this)->IsEmpty()) return box;

	double xx0, yy0, zz0, xx1, yy1, zz1;
	xx0 = (x0 > b.x0) ? x0 : b.x0;
	yy0 = (y0 > b.y0) ? y0 : b.y0;
	zz0 = (z0 > b.z0) ? z0 : b.z0;
	xx1 = (x1 < b.x1) ? x1 : b.x1;
	yy1 = (y1 < b.y1) ? y1 : b.y1;
	zz1 = (z1 < b.z1) ? z1 : b.z1;
	if ((xx1 > xx0) && (yy1 > yy0) && (zz1 > zz0)) {
		box = CBox3D(xx0, yy0, zz0, xx1, yy1, zz1);
	}
	return box;
}

void CBox3D::operator&=(BOX3D b)
{
	CBox3D box = (*this)&b;
	*this = box;
}

BOOL CBox3D::operator<<(BOX3D  b) const
{
	if (IsEmpty()) return TRUE;

	if ((x0 >= b.x0) && (y0 >= b.y0) && (z0 >= b.z0) &&
		(x1 <= b.x1) && (y1 <= b.y1) && (z1 <= b.z1)) return TRUE;
	else
		return FALSE;
}

BOOL CBox3D::operator>>(BOX3D b) const
{
	if (((CBox3D)b).IsEmpty()) return TRUE;

	if ((x0 >= b.x0) && (y0 >= b.y0) && (z0 >= b.z0) &&
		(x1 <= b.x1) && (y1 <= b.y1) && (z1 <= b.z1)) return FALSE;
	else
		return TRUE;
}

BOOL CBox3D::operator>>(POINT3D p) const
{
	if ((x0 <= p.x) && (y0 <= p.y) && (z0 <= p.z) &&
		(x1 >= p.x) && (y1 >= p.y) && (z1 >= p.z)) return TRUE;
	else
		return FALSE;
}

//// get the intersect box of this and box b.
CBox3D CBox3D::operator|(BOX3D b) const
{
	CBox3D box;

	if (((CBox3D *)this)->IsEmpty()) {
		box = b;
		return box;
	}
	if (((CBox3D)b).IsEmpty()) {
		box = *this;
		return box;
	}

	double xx0, yy0, zz0, xx1, yy1, zz1;
	xx0 = (x0 < b.x0) ? x0 : b.x0;
	yy0 = (y0 < b.y0) ? y0 : b.y0;
	zz0 = (z0 < b.z0) ? z0 : b.z0;
	xx1 = (x1 > b.x1) ? x1 : b.x1;
	yy1 = (y1 > b.y1) ? y1 : b.y1;
	zz1 = (z1 > b.z1) ? z1 : b.z1;
	if ((xx1 >= xx0) && (yy1 >= yy0) && (zz1 >= zz0)) {
		box = CBox3D(xx0, yy0, zz0, xx1, yy1, zz1);
	}
	return box;
}

void CBox3D::operator|=(BOX3D b)
{
	CBox3D box = (*this) | b;
	*this = box;
}

// get attribs
BOOL CBox3D::IsEmpty() const
{
	return	GeIsZero(Width()) &&
		GeIsZero(Height()) &&
		GeIsZero(Length());
}

double CBox3D::Width() const // Length of X direction
{
	return x1 - x0;
}

double CBox3D::Height() const // Length of Z direction
{
	return z1 - z0;
}
double CBox3D::Length() const // Length of Z direction
{
	return y1 - y0;
}

// relationship culation
// there may be four cases:
// <enumSeparated,enumIntersected>
CBox3D::RelaShip CBox3D::GetRelationWith(BOX3D b) const
{
	CBox3D box;
	box = (*this)&b;
	if (box.IsEmpty())
		return eSeparated;
	else
		return eIntersected;
}

void CBox3D::normalize()
{
	double xx0, yy0, xx1, yy1, zz0, zz1;
	xx0 = (x0 < x1) ? x0 : x1;
	xx1 = (x0 > x1) ? x0 : x1;
	yy0 = (y0 < y1) ? y0 : y1;
	yy1 = (y0 > y1) ? y0 : y1;
	zz0 = (z0 < z1) ? z0 : z1;
	zz1 = (z0 > z1) ? z0 : z1;
	x0 = xx0; y0 = yy0; x1 = xx1; y1 = yy1;
	z0 = zz0; z1 = zz1;
}

CBox3D CBox3D::operator+(VECTOR3D vect) const
{
	CBox3D box;

	box.x0 = x0 + vect.x;
	box.y0 = y0 + vect.y;
	box.z0 = z0 + vect.z;
	box.x1 = x1 + vect.x;
	box.y1 = y1 + vect.y;
	box.z1 = z1 + vect.z;

	return box;
}

void CBox3D::operator+=(VECTOR3D vect)
{
	x0 = x0 + vect.x;
	y0 = y0 + vect.y;
	z0 = z0 + vect.z;
	x1 = x1 + vect.x;
	y1 = y1 + vect.y;
	z1 = z1 + vect.z;
}

CBox3D CBox3D::operator-(VECTOR3D vect) const
{
	CBox3D box;

	box.x0 = x0 - vect.x;
	box.y0 = y0 - vect.y;
	box.z0 = z0 - vect.z;
	box.x1 = x1 - vect.x;
	box.y1 = y1 - vect.y;
	box.z1 = z1 - vect.z;

	return box;
}

void CBox3D::operator-=(VECTOR3D vect)
{
	x0 = x0 - vect.x;
	y0 = y0 - vect.y;
	z0 = z0 - vect.z;
	x1 = x1 - vect.x;
	y1 = y1 - vect.y;
	z1 = z1 - vect.z;
}
